#!/usr/bin/env python3
# Copyright (c) 2008-11 Qtrac Ltd. All rights reserved.
# This program or module is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version. It is provided for educational
# purposes and is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.

import locale
locale.setlocale(locale.LC_ALL, "")

import datetime
import gzip
import optparse
import os
import pickle
import re
import struct
import sys
import textwrap

import Incidents

def parse_options():
    reader_list = "manual m".split()
    writer_list = "manual m".split()
    parser = optparse.OptionParser(usage="""\
usage: %prog [options] infile outfile

Reads aircraft incident data from infile and writes the data to
outfile. The data formats used depend on the file extensions: .ait is text (UTF-8 encoding) and
.aip is pickle.
All formats are platform-independent.""")
    parser.add_option("-f", "--force", dest="force",
            action="store_true", default=False,
            help=("write the outfile even if it exists "
                  "[default: off]"))
    parser.add_option("-v", "--verbose", dest="verbose",
            action="store_true", default=False,
            help=("report results [default: off]"))
    parser.add_option("-r", "--reader", dest="reader",
            choices=reader_list,
            help=("reader (text): 'manual', 'm', [default: manual for text]"))
    parser.add_option("-w", "--writer", dest="writer",
            choices=writer_list,
            help=("'manual', 'm' [default: manual]"))
    parser.add_option("-z", "--compress", dest="compress",
            action="store_true", default=False,
            help=("compress .aip outfile [default: off]"))
    parser.add_option("-t", "--test", dest="test",
            action="store_true",
            help=("execute doctests and exit (use with -v for "
                  "verbose)"))
    opts, args = parser.parse_args()

    if opts.test:
        test(opts.verbose)
    if len(args) == 0:
        parser.error("no files have been specified")
    if len(args) != 2:
        parser.error("exactly two files must been specified")
    if args[0] == args[1]:
        parser.error("the two specified files must be different")
    source, target = args

    if not opts.force and os.path.exists(target):
        parser.error("cannot overwrite unless --force is used")
    if opts.compress and target[-1] not in "pb":
        parser.error("can only compress .aip files")

    valid_extensions = {".ait", ".aip"}
    extension = os.path.splitext(source)[1].lower()
    if extension not in valid_extensions:
        parser.error("unrecognized infile extension: '{0}'".format(
                     extension))
    if extension == ".ait" and not opts.reader:
        opts.reader = "manual"
    text_readers = frozenset({"manual", "m"})
    if ((extension == ".ait" and opts.reader not in text_readers) or
        (extension not in {".ait"} and opts.reader)):
        parser.error("invalid reader for infile")

    extension = os.path.splitext(target)[1].lower()
    if extension not in valid_extensions:
        parser.error("unrecognized outfile extension: '{0}'".format(
                     extension))
    readers = dict(m="manual")
    if opts.reader in readers:
        opts.reader = readers[opts.reader]
    writers = dict(m="manual")
    if opts.writer in writers:
        opts.writer = writers[opts.writer]
    if ((extension == ".aix" and opts.writer not in
         set(writers.keys()) | set(writers.values())) or
        (extension != ".aix" and opts.writer)):
        parser.error("invalid writer for outfile")

    return opts, source, target


def test(verbose):
    import doctest
    doctest.testmod(verbose=verbose)
    sys.exit()


def main():
    opts, source, target = parse_options()
    aircraft_incidents = Incidents.IncidentCollection()
    if aircraft_incidents.import_(source, opts.reader):
        if opts.verbose:
            print("imported {0} record{s} from '{1}'".format(
                  len(aircraft_incidents), source,
                  s = "s" if len(aircraft_incidents) != 1 else ""))
        if aircraft_incidents.export(target, opts.writer,
                                     opts.compress):
            if opts.verbose:
                print("exported {0} record{s} to   '{1}'".format(
                    len(aircraft_incidents), target,
                    s = "s" if len(aircraft_incidents) != 1 else ""))


main()
